1. User 영역에서 Kernel로의 데이터 흐름
-
애플리케이션(User Data 영역)에서 파일 입출력 함수를 호출하면, 바로 디스크에 쓰는 것이 아니라 File Driver(파일 드라이버) 계층을 거쳐 Kernel로 진입합니다.
-
데이터 전달 계층:
- 유저 애플리케이션 코드 (
printf,fopen,fread등) - C 표준 라이브러리 (I/O Buffer 관리)
- 시스템 콜 (
read,write등) - VFS(가상 파일 시스템) 및 파일 드라이버 (NTFS, EXT4 등)
- OS 커널 페이지 캐시(Page Cache) 및 블록 디바이스 드라이버
- 물리 디스크(SSD, HDD) / 터미널 장치
- 유저 애플리케이션 코드 (
2. 콘솔 입출력과 파일 I/O의 관계 (“모든 것은 파일이다”)
-
printf,scanf,gets_s,puts등 콘솔 입출력 함수는 새로운 기술이 아니며, 프로그램 구동 시 OS가 기본적으로 열어두는 표준 스트림(stdin,stdout)을 사용하는 파일 I/O와 완전히 동일한 구조입니다.stdin(표준 입력, FD 0): 읽기 전용 콘솔 입력 (키보드 매핑)stdout(표준 출력, FD 1): 쓰기 전용 콘솔 출력 (모니터 매핑)stderr(표준 에러, FD 2): 버퍼링 없이 즉시 출력되는 에러 스트림
-
“CON” 디바이스 파일 (Windows 기준)
- 파일 경로에
"CON"을 지정하면 콘솔 화면/키보드를 직접 파일로 열 수 있습니다. fopen("CON", "r"): 콘솔 키보드 입력을 읽기 전용으로 오픈 (stdin과 동일)fopen("CON", "w"): 콘솔 화면 출력을 쓰기 전용으로 오픈 (stdout과 동일)- 주의점:
"CON"파일은 읽기와 쓰기("r+"등)를 동시에 열 수 없으며, 시도 시 드라이버 충돌로 인해 오류가 발생합니다. (POSIX/리눅스 환경은"/dev/tty"매핑)
- 파일 경로에
3. FILE 인터페이스의 Page 단위(4KB) 버퍼링
-
FILE구조체를 통한 표준 I/O는 시스템 콜의 잦은 호출로 인한 오버헤드를 줄이기 위해, OS 메모리 관리 최소 단위인 Page 단위(기본 4KB)의 버퍼를 유저 공간에 할당하여 읽고 씁니다. -
버퍼링 3가지 모드 (
setvbuf설정 가능)- 완전 버퍼링 (
_IOFBF): 일반 디스크 파일. 4KB 버퍼가 꽉 차거나 닫힐 때만 디스크 I/O 실행 - 행 단위 버퍼링 (
_IOLBF):stdout. 개행 문자(\n)를 만나거나 버퍼가 찰 때 방출 - 무버퍼 (
_IONBF):stderr. 버퍼를 거치지 않고 즉각 전달
- 완전 버퍼링 (
4. fflush() 함수의 용도와 주의사항
-
역할: 출력 버퍼(Output Buffer)에 쌓여 있는 데이터를 물리 디스크나 화면으로 즉시 강제 방출(비우기)합니다.
-
주의사항:
- 예전 일부 구형 컴파일러에서 입력 버퍼를 비우기 위해
fflush(stdin)을 사용했으나, C 표준(C99/C11) 규격상 입력 스트림에 대한fflush()는 “정의되지 않은 동작(Undefined Behavior)“입니다. - 따라서
fflush는 출력 스트림에만 사용해야 합니다.
- 예전 일부 구형 컴파일러에서 입력 버퍼를 비우기 위해
표준 입력 버퍼 비우기 패턴:
int c;
while ((c = getchar()) != '\n' && c != EOF);